﻿namespace K9Nano.Caching;

public interface ITypedCache<TCachedValue> : ITypedCacheCleaner
{
    /// <summary>
    /// Adds a value for the specified key to the cache.
    /// <para>
    /// The <c>Add</c> method will <b>not</b> be successful if the specified
    /// <paramref name="key"/> already exists within the cache!
    /// </para>
    /// </summary>
    bool Add(string key, TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

    /// <summary>
    /// Puts a value for the specified key into the cache.
    /// <para>
    /// If the <paramref name="key"/> already exists within the cache, the existing value will
    /// be replaced with the new <paramref name="value"/>.
    /// </para>
    /// </summary>
    void Put(string key, TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

    TCachedValue Update(string key, Func<TCachedValue, TCachedValue> updateValue);

    TCachedValue? Get(string key);

    void Expire(string key, DateTime absoluteExpiration);

    void Expire(string key, TimeSpan slidingExpiration);

    TCachedValue AddOrUpdate(string key, TCachedValue addValue, Func<TCachedValue, TCachedValue> updateValue, TimeSpan? slidingTimeout = null,
        TimeSpan? absoluteTimeout = null);

    TCachedValue AddOrUpdate(string key, TCachedValue addValue, TimeSpan? slidingTimeout = null,
        TimeSpan? absoluteTimeout = null)
        => AddOrUpdate(key, addValue, _ => addValue, slidingTimeout, absoluteTimeout);

    TCachedValue GetOrAdd(string key, TCachedValue value);

    TCachedValue GetOrAdd(string key, Func<string, TCachedValue> valueFactory);

    bool TryGetOrAdd(string key, Func<string, TCachedValue> valueFactory, out TCachedValue? value);

    bool TryUpdate(string key, Func<TCachedValue, TCachedValue> updateValue, out TCachedValue? value);

    bool Add(TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

    void Put(TCachedValue value, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null);

    TCachedValue Update(Func<TCachedValue, TCachedValue> updateValue);

    TCachedValue? Get();

    void Expire(DateTime absoluteExpiration);

    void Expire(TimeSpan slidingExpiration);

    bool Exists(string key);

    bool Exists();

    bool Remove();

    TCachedValue AddOrUpdate(TCachedValue addValue, Func<TCachedValue, TCachedValue> updateValue, TimeSpan? slidingTimeout = null,
        TimeSpan? absoluteTimeout = null);

    TCachedValue AddOrUpdate(TCachedValue addValue, TimeSpan? slidingTimeout = null, TimeSpan? absoluteTimeout = null)
        => AddOrUpdate(addValue, _ => addValue, slidingTimeout, absoluteTimeout);

    TCachedValue GetOrAdd(TCachedValue value);

    TCachedValue GetOrAdd(Func<string, TCachedValue> valueFactory);

    bool TryGetOrAdd(Func<string, TCachedValue> valueFactory, out TCachedValue? value);

    bool TryUpdate(Func<TCachedValue, TCachedValue> updateValue, out TCachedValue? value);
}
